# %%
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time

# 读取数据
# dir_file = "../data/railway_okzhuanginfo_去尾.csv"

dir_file = "../data/railway_okzhuanginfo_delTail_token.csv"
train = pd.read_csv(dir_file)
y = None
if dir_file[-9:-4] == 'token':
    y = train['y']
    train.drop('y', axis=1)

# 删掉指定的非数据列
train = train.drop(['id', 'ZhuangNum', 'ProjectID', 'Starttime', 'Endtime', 'DeviceNum', 'State'], axis=1)
train.head(3)

# 检查每个变量中缺失值的百分比。若不为0，则有缺失
a = train.isnull().sum() / len(train) * 100

# 在变量中保存小于阈值的列名
variables = train.columns
variable = []
for i in range(0, len(variables)):
    if a[i] <= 20:  # 设置阈值为20%,小于20的保留
        variable.append(variables[i])

# 低方差滤波（Low Variance Filter）
'''
如果我们有一个数据集，其中某列的数值基本一致，也就是它的方差非常低，那么这个变量还有价值吗？
和上一种方法的思路一致，我们通常认为低方差变量携带的信息量也很少，所以可以把它直接删除。
放到实践中，就是先计算所有变量的方差大小，然后删去其中最小的几个。
需要注意的一点是：方差与数据范围相关的，因此在采用该方法前需要对数据做归一化处理。
'''
# 放在示例中，我们先填上缺失值：
'''
让我们首先使用已知 Upspeed 观测值的中值来估算 Upspeed 列中的缺失值。
对于 Incurrent 列，我们将使用已知 Incurrent 值的众数来估算缺失值：
'''
train['Upspeed'].fillna(train['Upspeed'].median(), inplace=True)
train['DownSpeed'].fillna(train['DownSpeed'].median(), inplace=True)
train['Incurrent'].fillna(train['Incurrent'].mode()[0], inplace=True)
train['OutCurrent'].fillna(train['OutCurrent'].mode()[0], inplace=True)

# 检查缺失值是否已经被填充：
train.isnull().sum() / len(train) * 100

# 再计算所有数值变量的方差：
train.var()  # 此时获得高相关变量 OutCurrent (最高方差)

# %%
# 如上图所示，和其他变量相比，Lon的方差非常小，因此可以把它直接删除。
numeric = train
var = numeric.var()
numeric = numeric.columns
need_drop_col = []

for i in range(0, len(var)):
    if var[i] < 10:  # 将阈值设置为10％
        need_drop_col.append(numeric[i])

print(need_drop_col)

train.drop(need_drop_col, axis=1, inplace=True)

# %%  高相关滤波（High Correlation filter）
# 相关性计算
train.corr()

# %% 标准化
from sklearn import preprocessing

# Z-Score标准化
# 建立StandardScaler对象
zscore = preprocessing.StandardScaler()
# 标准化处理
df_zs = zscore.fit_transform(train)
df = train.values  # train.columns ['RealLength', 'Pentime', 'Totalslurry', 'Totalconcrete', 'Incurrent', 'OutCurrent', 'Verticality']

# %% == PCA ================================================================
from sklearn.decomposition import PCA
from util import draw_func_equation

t1 = time.time()
n_components = 3
pca = PCA(n_components=n_components)
pca_fit = pca.fit(df_zs)  # 再通过 pca_fit.transform([[...一个7列的二维数组...]])
pca_result = pca_fit.transform(df_zs)

'''
在这种情况下，n_components将决定转换数据中主成分的数量。让我们想象一下使用这 3 个组件解释了多少差异。
我们将使用explained_variance_ratio_来计算相同的值。
上面的红色线说明了一共有多少方差可以被解释
下面的蓝线表示每组数据解释了多少方差(从0开始,整数点的数据)
'''
plt.figure()
plt.plot(range(n_components), pca.explained_variance_ratio_)
plt.plot(range(n_components), np.cumsum(pca.explained_variance_ratio_))
for a, b in zip(range(n_components), np.cumsum(pca.explained_variance_ratio_)):
    # 在实际坐标(a,b)处显示"(a, round(b, 3))"
    plt.text(a, b, (a, round(b, 3)), ha='center', va='bottom', fontsize=10)
plt.title("component-wise and cumulative explained variance")  # 组件方式和累积解释方差
plt.show()

print("PCA 耗时: %.2f s" % (time.time() - t1))  # 0.25s

# 导出数据,并画三维图
# operate_csv.getCsv("../data/pca_result.csv", pca_result)
# draw_func_equation.plot_embedding_2d(pca_result, y)
draw_func_equation.plot_embedding_3d(pca_result, y, True)

from 降维.PCA import pca_SelfRealization

d1, d2 = pca_SelfRealization.pca(df_zs, 0.5)

# %% == KPCA ================================================================
print("%% == KPCA ================================================================")
from sklearn.decomposition import KernelPCA

t1 = time.time()
n_components = 3  # 这个数是几不影响PCA的结果,只影响返回的维数. 返回计算结果的前n列, n越小,计算越快
k_pca = KernelPCA(n_components=n_components, kernel='rbf')
k_pca_fit = k_pca.fit(df_zs)  # 再通过 k_pca_fit.transform([[...一个7列的二维数组...]])
k_pca_result = k_pca_fit.transform(df_zs)

plt.figure()
sum_lambda = sum(k_pca.eigenvalues_)  # Attribute `lambdas_` was deprecated in version 1.0 and will be removed in 1.2. Use `eigenvalues_` instead
k_explained_variance_ratio_ = np.zeros(3)
# 画折线
for i in range(n_components):
    k_explained_variance_ratio_[i] = k_pca.lambdas_[i] / sum_lambda
plt.plot(range(n_components), k_explained_variance_ratio_, label="可解释方差")
plt.plot(range(n_components), np.cumsum(k_explained_variance_ratio_), label="解释方差占比")
# 画坐标点
for a, b in zip(range(n_components), np.cumsum(k_explained_variance_ratio_)):
    plt.text(a, b, (a, round(b, 3)), ha='center', va='bottom', fontsize=10)  # 在实际坐标(a,b)处显示"(a, round(b, 3))"
plt.title("component-wise and cumulative explained variance")  # 组件方式和累积解释方差
plt.show()

print("K_PCA 耗时: %.2f s" % (time.time() - t1))  # 2.0s

# 导出数据,并画三维图

# operate_csv.writeToCsv("../data/k_pca_result.csv", pca_result)
# 画图时,画2d还是3d,和n_component没有关系,因为PCA的原则就是取主成分,n_component=2的列,就是n_component=3的前两列
# draw_func_equation.plot_embedding_2d(k_pca_result, y)
# draw_func_equation.plot_embedding_3d(k_pca_result, y, True)

# %% == RBF 中心点随机选取 ========================================================
print("%% == RBF 中心点随机选取 ========================================================")
from machine_learning.network.RBFNetwork3 import MyRBF_NeuralNetwork

# I = 10
# plt.figure(figsize=(8, 6))
# plt.title("Comparison of PCA and KPCA")
#
# # rbf regression. RBF: param1:输入维度; param2:中心点个数,即隐含层节点个数; param3:输出维度
# rbf = MyRBF_NeuralNetwork(pca_result.shape[1], 10, 1)
# k_rbf = MyRBF_NeuralNetwork(k_pca_result.shape[1], 10, 1)
#
# line1 = np.empty(shape=(I,))
# line2_k = np.empty(shape=(I,))
#
# for i in range(I):
#     rbf.fit_random_center(pca_result, y)
#     # z = rbf.predict(pca_result)
#     line1[i] = rbf.get_accuracy(y)
#     print("PCA correct rate: ", line1[i])
#
#     k_rbf.fit_random_center(k_pca_result, y)
#     # zk = k_rbf.predict(k_pca_result)
#     line2_k[i] = k_rbf.get_accuracy(y)
#     print("KPCA correct rate: ", line2_k[i])
#
# plt.plot(range(I), line1, label="PCA")
# plt.plot(range(I), line2_k, label="KPCA")
# plt.ylim((0, 1))
# plt.legend()  # 和label参数一起用
#
# plt.show()

# %% == RBF 中心点通过梯度下降迭代,有监督 =====================================================
print("%% == RBF 中心点通过梯度下降迭代,有监督 =====================================================")
from machine_learning.network import RBFNetwork1

# Y = np.array(y).reshape((y.shape[0], 1))
# rbf = RBFNetwork1.RBFNetwork(pca_result.shape[1], 10, Y.shape[1], pca_result, Y, learning_rate=0.001)
# rbf.fit(100)  # 训练次数
# rbf.transform(pca_result)
# print("correct rate: ", rbf.get_accuracy(), "%")
#
# rbf = RBFNetwork1.RBFNetwork(k_pca_result.shape[1], 10, Y.shape[1], k_pca_result, Y, learning_rate=0.001)
# rbf.fit(100)  # 训练次数
# rbf.transform(k_pca_result)
# print("correct rate: ", rbf.get_accuracy(), "%")

# %% == RBF 中心点通过KMeans聚类,无监督 =====================================================
print("%% == RBF 中心点通过KMeans聚类,无监督 =====================================================")

# PCA结果. RBF: param1:输入维度; param2:中心点个数,即隐含层节点个数; param3:输出维度
rbf = MyRBF_NeuralNetwork(pca_result.shape[1], 10, 1)
rbf.fit_KMeans_center(pca_result, y)
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))
# KPCA结果
rbf = MyRBF_NeuralNetwork(k_pca_result.shape[1], 10, 1)
rbf.fit_KMeans_center(k_pca_result, y)
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))
#
# ## 多次迭代对比
# I = 10
# plt.figure(figsize=(8, 6))
# plt.title("Comparison of PCA and KPCA")
#
# line1 = np.empty(shape=(I,))
# line2_k = np.empty(shape=(I,))
# for i in range(I):
#     # rbf regression. RBF: param1:输入维度; param2:中心点个数,即隐含层节点个数; param3:输出维度
#     rbf = MyRBF_NeuralNetwork(pca_result.shape[1], 10, 1)
#     rbf.fit_KMeans_center(pca_result, y)
#     line1[i] = rbf.get_accuracy(y)
#     print("PCA correct rate: ", line1[i])
#
#     # KPCA结果
#     k_rbf = MyRBF_NeuralNetwork(k_pca_result.shape[1], 10, 1)
#     k_rbf.fit_KMeans_center(k_pca_result, y)
#     line2_k[i] = k_rbf.get_accuracy(y)
#     print("KPCA correct rate: ", line2_k[i])
#
# plt.plot(range(I), line1, label="PCA")
# plt.plot(range(I), line2_k, label="KPCA")
# plt.ylim((0, 1))
# plt.legend()  # 和label参数一起用
#
# plt.show()

# %% == RBF 中心点通过CMeans聚类,无监督 =====================================================
print("%% == RBF 中心点通过CMeans聚类,无监督 =====================================================")

# PCA结果
rbf = MyRBF_NeuralNetwork(pca_result.shape[1], 10, 1)
rbf.fit_FCMeans_center(pca_result, y)
# 模糊聚类的每一个点不明确属于某一个簇,因此没有self.label_pred, 所以画不出图
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))
# KPCA结果
rbf = MyRBF_NeuralNetwork(k_pca_result.shape[1], 10, 1)
rbf.fit_FCMeans_center(k_pca_result, y)
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))

# %% == RBF 中心点通过DBSCAN聚类,无监督 =====================================================
print("%% == RBF 中心点通过DBSCAN聚类,无监督 =====================================================")

# PCA结果
rbf = MyRBF_NeuralNetwork(pca_result.shape[1], 10, 1)
rbf.fit_DBSCAN_center(pca_result, y, 0.01, 15)
print(rbf.centers.shape)
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))
# KPCA结果
rbf = MyRBF_NeuralNetwork(k_pca_result.shape[1], 10, 1)
rbf.fit_DBSCAN_center(k_pca_result, y, 0.01, 15)  # 0.01, 15 ==> 99.6%
# rbf.cluster_plot_3d()
print("correct rate: ", rbf.get_accuracy(y))
